/************************************************************************
 * The code is owned by mainframer.cn and Shang Tao
 * Without aproval of mainframer.cn and Shang Tao, removing the copyright
 * infomation is regarded as invassion of proprietary copyright
 ***********************************************************************/
package com.mr.qa.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.mr.qa.GlobalConfigs;
import com.mr.qa.UserSession;
import com.mr.qa.UserSessionUtil;
import com.mr.qa.action.UserAction;
import com.mr.qa.bo.User;


public class QaAppFilter implements Filter
{
    private static final Logger logger = Logger.getLogger(QaAppFilter.class);    
    
    private static String charset = "";
    
    FilterConfig _filterConfig = null;
    public QaAppFilter()
    {
    }
    public void init(FilterConfig filterConfig)
    {
        _filterConfig = filterConfig;
        charset = filterConfig.getInitParameter("charset");
        GlobalConfigs.WEB_PHISICAL_ROOT_LOCATION = _filterConfig.getServletContext().getRealPath("/");
        logger.info("System is booted at "+new Date());
    }
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain filterChain) throws UnsupportedEncodingException, 
                                                     IOException, 
                                                     ServletException
    {
            servletRequest.setCharacterEncoding(charset);
            //invalidate the user session and disable the auto login
            disableUser(servletRequest,servletResponse);
            //auto login
            int autoLoginResult = autoLogin(servletRequest,servletResponse);
            //logger.info("autoLoginResult="+autoLoginResult);
            //update user score and new message size
            //autoLogin has updated the user dynamic info
            if(autoLoginResult != 6)updateUserDynamicInfo(servletRequest);
            
            if(!hasAccessToLog(servletRequest)) 
            {
                throw new ServletException("User Has no right to do this");
                //go to error page    
            }
            else
                filterChain.doFilter(servletRequest,servletResponse);
            
    }

    public void destroy()
    {
        charset = null;
    }
    
    private boolean hasAccessToLog(ServletRequest servletRequest) 
    {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String url = request.getRequestURL().toString();
        if(url.indexOf("iask_log.") >= 0) 
        {
            UserSession us = UserSessionUtil.getUserSession(request);
            if(us == null)
            {
                logger.warn("Not logged in User has no right to view log");
                return false;
            }
            if(!"1".equals(us.getType()))
            {
                logger.warn("User"+us.getUserId()+":"+us.getLoginName()+" has no right to view log");
                return false;
            }
       }
       return true;
    }
        
    private String autoLoginFailureIDInSession = "autoLoginFailure";
    
    //2008.6.25 after the admin disables the user, filter will invalidate the user session
    
    private void disableUser(ServletRequest servletRequest,ServletResponse servletResponse)
    {
        if(GlobalConfigs.PROHIBITED_USERS == null || GlobalConfigs.PROHIBITED_USERS.length() == 0)return;
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        UserSession us = UserSessionUtil.getUserSession(request);
        if(us == null)return;
        String userId = us.getUserId()+",";
        if(!GlobalConfigs.PROHIBITED_USERS.endsWith(","))
            GlobalConfigs.PROHIBITED_USERS += ",";
        if(GlobalConfigs.PROHIBITED_USERS.indexOf(userId) >= 0)
        {
            //invalidate the user session
            request.getSession().invalidate();
            //disable the auto login
            request.getSession().setAttribute(autoLoginFailureIDInSession,"1");
            Cookie autoLoginCookie = new Cookie("autoLogin","");
            HttpServletResponse response = (HttpServletResponse)servletResponse;
            response.addCookie(autoLoginCookie);
            //remove the user
            GlobalConfigs.PROHIBITED_USERS = GlobalConfigs.PROHIBITED_USERS.replaceFirst(userId,"");
        }
        
    }
    
    private void updateUserDynamicInfo(ServletRequest servletRequest)
    {
        try
        {
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            String updated = (String)request.getAttribute("UserDynamicInfoUpdated");
            if("true".equals(updated))return;
            UserSession us = UserSessionUtil.getUserSession(request);
            if(us == null)return;
            UserAction ua = new UserAction();
            User user = ua.getForUodateUserSession(us.getUserId());
            if(user == null)return;
            int newMessageSize = user.getNewMessages().size();
            int score = user.getUserScore().getTotalScore();
            int money = user.getUserMoney().getTotalMoney();
            us.setNewMessageSize(newMessageSize);
            us.setScore(score);
            us.setMoney(money);
            UserSessionUtil.saveUserSession(us,request);
            request.setAttribute("UserDynamicInfoUpdated","true");
        }
        catch(Exception e)
        {
            logger.error("updateUserDynamicInfo exception:"+e);
        }
        
    }
    
    //when the user logout,the filter still tries to log on automatically,how to prevent this
    /**
     * 
     * @param servletRequest
     * @param servletResponse
     * @return int
     * 1 autoLoginFailure
     * 2 loginned
     * 3 no cookie
     * 4 the user has logouted
     * 5 no login name in cookie
     * 6 auto login successfully
     * 7 other
     */
    private int autoLogin(ServletRequest servletRequest,ServletResponse servletResponse)
    {
        try
        {
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            String ifAutoLoginFailure = (String)request.getSession().getAttribute(autoLoginFailureIDInSession);
            if(ifAutoLoginFailure != null)return 0;
            //UserAction.printlnCookies("AppFiter1",request);
            UserSession us = UserSessionUtil.getUserSession(request);
            //logger.info("autoLogin 0");
            if(us != null)return 1;
            Cookie[] cookies = request.getCookies();
            //logger.info("autoLogin 00");
            if(cookies == null || cookies.length == 0)return 2;
            Cookie cookie = null;
            String loginName = "";
            String loginStyle = "";
            String lastLogonDatetime = "";
            String logout = "";
            //logger.info("autoLogin 1");
            for(int i=0;i<cookies.length;i++)
            {
                cookie = cookies[i];
                if("loginStyle".equals(cookie.getName()))
                {
                    loginStyle = cookie.getValue();
                }
                else if("loginName".equals(cookie.getName()))
                {
                    loginName = cookie.getValue();
                }
                else if("lastLogonTime".equals(cookie.getName()))
                {
                    lastLogonDatetime = cookie.getValue();
                }
                else if("logout".equals(cookie.getName()))
                {
                    logout = cookie.getValue();
                }
            }
            //if the user logouts, don't logon automatically
            if("true".equals(logout))
            {
                //logger.info("logout=true");
                return 4;
            }
            if(loginName == null || loginName.length() <= 0)return 5;
            
            if("autoLogin".equals(loginStyle))
            {
                UserAction ua = new UserAction();
                Date logonDate = new Date();
                User user = ua.autoLogin(loginName,lastLogonDatetime,logonDate);
                if(user != null)
                {
                    /*
                    us = new UserSession(user.getId(),user.getLoginName(), user
                                                                .getType(), user.getState());
                    us.setName(user.getName());
                    us.setSignature(user.getSignature());
                    us.setEmail(user.getEmail());
                    us.setMobile(user.getMobile());
                    us.setIsSuper(user.getIsSuper());
                    //2008.6.24
                    us.setPermissions(user.getPermissions());
                    us.setRegisterDate(user.getRegisterDate());
                    */
                    us = new UserSession();
                    UserSessionUtil.transferUserToUserSession(user,us);
                    UserSessionUtil.saveUserSession(us, request);
                    
                    Cookie lastLogonDateCookie = new Cookie("lastLogonTime",""+logonDate.getTime());
                    int maxAge = 2592000;
                    lastLogonDateCookie.setMaxAge(maxAge);
                    
                    Cookie logoutCookie = new Cookie("logout","");
                    HttpServletResponse response = (HttpServletResponse)servletResponse;
                    
                    response.addCookie(lastLogonDateCookie);
                    response.addCookie(logoutCookie);
                    return 6;
                }
                else
                {
                    //tell the filter not to autolog next time
                    request.getSession().setAttribute(autoLoginFailureIDInSession,"1");
                }
            }
            //UserAction.printlnCookies("AppFiter2",request);
        }
        catch(Exception e)
        {
            logger.error("autoLogin exception:"+e);
        }
        return 7;
    }
    
    
    
}
